package ua.sumdu.LukyanovChalyi.Server;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.net.ServerSocket;
import java.net.Socket;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

public class Server implements Observer {

    private static ServerSocket ss;
    private static final Logger logger = Logger.getLogger(Server.class);
    private static List<ClientConnection> clients;
    private static ViewServer viewServer = null;

    public Server(int port) throws IOException {
        File f = new File("log4j.xml");
        if (!f.exists()) {
            throw new FileNotFoundException("Can't open file with logger settings");
        }
        DOMConfigurator.configure("log4j.xml");
        viewServer = new ViewServer();
        ss = new ServerSocket(port);
    }

    public static void main(String[] args) {
        try {
            int port = Integer.parseInt(args[0]);
            if (port < 0 || port > 65535) {
                logger.info("Port cant be less zero or bigger that 65535");
                viewServer.showMessage("Port cant be less zero or bigger that 65535");
                System.exit(0);
            }
            Server server = new Server(port);
            Model model = new Model();

            clients = new ArrayList<ClientConnection>();
            System.out.println("Server Started");
            while (true) {
                Socket socket = ss.accept();
                ClientConnection client = new ClientConnection(server, socket, model, viewServer);
                clients.add(client);
                new Thread(client).start();
            }

        } catch (ArrayIndexOutOfBoundsException e) {
            viewServer.showException("Input port!", e);
        } catch (NumberFormatException e) {
            viewServer.showException("Port must be number", e);
        } catch (FileNotFoundException e) {
            // Can't do nothing. Can't create view and show message. 
            System.out.println(e.getMessage());
        } catch (IOException e) {
            viewServer.showException("Exception with network. May be I have already start server", e);
        } finally {
            try {
                if (ss != null) {
                    ss.close();
                }
            } catch (IOException e) {
                viewServer.showException("Input/output exception while closing socket", e);
            }
        }
    }

    @Override
    public void update(Observable o, Object param) {
        for (ClientConnection cc : clients) {
            try {
                cc.createXMLToClient((Object[]) param);
            } catch (IOException ex) {
                viewServer.showException("Error while sending answer to client ", ex);
            } catch (TransformerException ex) {
                viewServer.showException("Error while transform xml to stream ", ex);
            } catch (ParserConfigurationException e1) {
                viewServer.showException("Serious configuration error ", e1);
            }
        }
    }

    public void disconnect(ClientConnection cc) {
        clients.remove(cc);
    }
}
